package com.jackrain.nea.util;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;

import com.aliyun.opensearch.DocumentClient;
import com.aliyun.opensearch.OpenSearchClient;
import com.aliyun.opensearch.SearcherClient;
import com.aliyun.opensearch.sdk.dependencies.com.google.common.collect.Lists;
import com.aliyun.opensearch.sdk.generated.OpenSearch;
import com.aliyun.opensearch.sdk.generated.commons.OpenSearchClientException;
import com.aliyun.opensearch.sdk.generated.commons.OpenSearchException;
import com.aliyun.opensearch.sdk.generated.commons.OpenSearchResult;
import com.aliyun.opensearch.sdk.generated.document.Command;
import com.aliyun.opensearch.sdk.generated.document.DocumentConstants;
import com.aliyun.opensearch.sdk.generated.search.Config;
import com.aliyun.opensearch.sdk.generated.search.SearchFormat;
import com.aliyun.opensearch.sdk.generated.search.SearchParams;
import com.aliyun.opensearch.sdk.generated.search.general.SearchResult;
import com.jackrain.nea.config.PropertiesConf;
import com.jackrain.nea.web.face.User;
import com.jackrain.nea.web.query.QueryEngine;
import lombok.extern.slf4j.Slf4j;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.sql.Timestamp;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.LockSupport;

/**
 * @author nathan
 */
@Slf4j
public class OpenSearchDoc {

    public static OpenSearchClient client;
//    private static String sql = "SELECT a.index,a.sql,a.isclient,a.isstore FROM c_opensearchdoc a where a.table=? and a.opts=?";
    private static String logSql = "INSERT INTO  ali_opensearch_log(id,indexname,tablename,info,is_success,creationdate)\n" +
            "VALUES(?,?,?,?,?,?)";

    public OpenSearchDoc(){
        if(client == null){
            PropertiesConf pconf = (PropertiesConf) ApplicationContextHandle.getBean("propertiesConf");
            String accesskey = pconf.getProperty("ons.accessKey");
            String secret = pconf.getProperty("ons.secretKey");
            String host = "http://opensearch-cn-hangzhou.aliyuncs.com";
            Map<String,Object> opts = new HashMap<String,Object>();
            OpenSearch openSearch = new OpenSearch(accesskey, secret, host);
            client = new OpenSearchClient(openSearch);
        }
    }

    /**
     * after db operation
     * @param tableName
     * @param ids db查询中where条件的值
     * @param conditionCol db查询中where条件的字段名
     */
    public void add(String tableName, Object[] ids, String conditionCol,String sql,String index){
        //日志流
        StringWriter sw = new StringWriter();
        PrintWriter pw = new PrintWriter(sw);
        DocumentClient doc = new DocumentClient(client);
        Object[] objects = null;
        if(ids != null){
            objects = new Object[ids.length];
            for(int i=0; i<ids.length; i++){
                objects[i] = ids[i];
            }
        }

        StringBuffer buffer = new StringBuffer();
        String docSql;
        if(conditionCol != null && ids.length == 1){
            docSql = sql + " and a." + conditionCol + "=?";
        }else if(conditionCol != null && ids.length > 1){
            for(int i=0; i<ids.length; i++){
                buffer.append(",?");
            }
            docSql = sql + " and a." + conditionCol + " in("+buffer.substring(1)+")";
        }else{
            docSql = sql;
        }
        JSONArray ja = QueryEngine.getInstance().doQueryObjectArray(docSql,objects);
        if(ja != null){
            int cnt = ja.size()/100;
            int mod = ja.size()%100;
            for(int i=0; i<=cnt; i++){
                JSONArray data = new JSONArray();
                for(int j=0; (j<100&&i<cnt)||(i==cnt&&j<mod); j++){
                    JSONObject o = new JSONObject();
                    o.put(DocumentConstants.DOC_KEY_CMD, Command.ADD.toString());
                    o.put(DocumentConstants.DOC_KEY_FIELDS,ja.get(i * 100 + j));
                    data.add(o);
                }
                try {
                    OpenSearchResult result = doc.push(data.toJSONString(),index,tableName);
                    if(!result.getResult().equalsIgnoreCase("true")){
                        QueryEngine.getInstance().executeUpdate(logSql,new Object[]{com.jackrain.nea.core.db.Tools.getSequence("ali_opensearch_log"),
                                index,tableName,result.getTraceInfo()+"\n"+data.toJSONString(),"N",new Timestamp(System.currentTimeMillis())});
                    }
                } catch (Exception e) {
                    e.printStackTrace(pw);
                    QueryEngine.getInstance().executeUpdate(logSql,new Object[]{com.jackrain.nea.core.db.Tools.getSequence("ali_opensearch_log"),
                            index,tableName,sw.toString()+"\n"+data.toJSONString(),"N",new Timestamp(System.currentTimeMillis())});
                }
                LockSupport.parkNanos(TimeUnit.MILLISECONDS.toNanos(100L));
            }
        }
    }


    /**
     * before db operation
     * @param tableName
     * @param ids db查询中where条件的值
     * @param conditionCol db查询中where条件的字段名
     */
    public void delete(String tableName, Object[] ids, String conditionCol,String sql,String index){
        //日志流
        StringWriter sw = new StringWriter();
        PrintWriter pw = new PrintWriter(sw);
        DocumentClient doc = new DocumentClient(client);
        Object[] objects = null;
        if(ids != null){
            objects = new Object[ids.length];
            for(int i=0; i<ids.length; i++){
                objects[i] = ids[i];
            }
        }

        StringBuffer buffer = new StringBuffer();
        String docSql;
        if(conditionCol != null && ids.length > 0){
            for(int i=0; i<ids.length; i++){
                buffer.append(",?");
            }
            docSql = sql + " and a." + conditionCol + " in("+buffer.substring(1)+")";
        }else{
            docSql = sql;
        }

        JSONArray ja = QueryEngine.getInstance().doQueryObjectArray(docSql,objects);
        if(ja != null){
            int cnt = ja.size()/100;
            int mod = ja.size()%100;
            for(int i=0; i<=cnt; i++){
                JSONArray data = new JSONArray();
                for(int j=0; (j<100&&i<cnt)||(i==cnt&&j<mod); j++){
                    JSONObject o = new JSONObject();
                    o.put(DocumentConstants.DOC_KEY_CMD, Command.DELETE.toString());
                    o.put(DocumentConstants.DOC_KEY_FIELDS,ja.get(i * 100 + j));
                    data.add(o);
                }
                try {
                    OpenSearchResult result = doc.push(data.toJSONString(),index,tableName);
                    if(!result.getResult().equalsIgnoreCase("true")){
                        QueryEngine.getInstance().executeUpdate(logSql,new Object[]{com.jackrain.nea.core.db.Tools.getSequence("ali_opensearch_log"),
                                index,tableName,result.getTraceInfo()+"\n"+data.toJSONString(),"N",new Timestamp(System.currentTimeMillis())});
                    }

                } catch (Exception e) {
                    e.printStackTrace(pw);
                    QueryEngine.getInstance().executeUpdate(logSql,new Object[]{com.jackrain.nea.core.db.Tools.getSequence("ali_opensearch_log"),
                            index,tableName,sw.toString()+"\n"+data.toJSONString(),"N",new Timestamp(System.currentTimeMillis())});

                }
                LockSupport.parkNanos(TimeUnit.MILLISECONDS.toNanos(100L));
            }
        }
    }

    /**
     * 通过id直接删除opensearch数据
     * @param tableName
     * @param ids opensearch 主键id
     */
    public void delete(String tableName,Long[] ids,String index){
        //日志流
        StringWriter sw = new StringWriter();
        PrintWriter pw = new PrintWriter(sw);
        DocumentClient doc = new DocumentClient(client);
        if(ids != null){
            int cnt = ids.length/100;
            int mod = ids.length%100;
            for(int i=0; i<=cnt; i++){
                JSONArray data = new JSONArray();
                for(int j=0; (j<100&&i<cnt)||(i==cnt&&j<mod); j++){
                    JSONObject o = new JSONObject();
                    JSONObject id = new JSONObject();
                    id.put("id",ids[i * 100 + j]);
                    o.put(DocumentConstants.DOC_KEY_CMD, Command.DELETE.toString());
                    o.put(DocumentConstants.DOC_KEY_FIELDS,id);
                    data.add(o);
                }
                log.error("--------------------"+data.toJSONString()+"-----------------");
                try {
                    OpenSearchResult result = doc.push(data.toJSONString(),index,tableName);
                    if(!result.getResult().equalsIgnoreCase("true")){
                        QueryEngine.getInstance().executeUpdate(logSql,new Object[]{com.jackrain.nea.core.db.Tools.getSequence("ali_opensearch_log"),
                                index,tableName,result.getTraceInfo()+"\n"+data.toJSONString(),"N",new Timestamp(System.currentTimeMillis())});
                    }

                } catch (Exception e) {
                    e.printStackTrace(pw);
                    QueryEngine.getInstance().executeUpdate(logSql,new Object[]{com.jackrain.nea.core.db.Tools.getSequence("ali_opensearch_log"),
                            index,tableName,sw.toString()+"\n"+data.toJSONString(),"N",new Timestamp(System.currentTimeMillis())});

                }
                LockSupport.parkNanos(TimeUnit.MILLISECONDS.toNanos(100L));
            }

        }
    }

    /**
     * 初始化opensearch
     * @param tableName
     */
    public int init(String tableName,String index){
        //日志流
        StringWriter sw = new StringWriter();
        PrintWriter pw = new PrintWriter(sw);
        DocumentClient doc = new DocumentClient(client);
        SearcherClient searcherClient = new SearcherClient(client);
        Config config = new Config(Lists.newArrayList(index));
        config.setSearchFormat(SearchFormat.JSON);
        config.setStart(0);
        config.setHits(5000);
        // 创建参数对象
        SearchParams searchParams = new SearchParams(config);
        // 执行返回查询结果
        SearchResult searchResult=null;
        try {
            searchResult = searcherClient.execute(searchParams);
        } catch (OpenSearchException e) {
            e.printStackTrace();
        } catch (OpenSearchClientException e) {
            e.printStackTrace();
        }
        if(searchResult != null){
            JSONObject searchJson = com.alibaba.fastjson.JSON.parseObject(searchResult.getResult());
            JSONArray ja = searchJson.getJSONObject("result").getJSONArray("items");
            if(ja != null){
                int cnt = ja.size()/100;
                int mod = ja.size()%100;
                for(int i=0; i<=cnt; i++){
                    JSONArray data = new JSONArray();
                    for(int j=0; (j<100&&i<cnt)||(i==cnt&&j<mod); j++){
                        JSONObject o = new JSONObject();
                        JSONObject id = new JSONObject();
                        id.put("id",((JSONObject)ja.get(i * 100 + j)).getLongValue("id"));
                        o.put(DocumentConstants.DOC_KEY_CMD, Command.DELETE.toString());
                        o.put(DocumentConstants.DOC_KEY_FIELDS,id);
                        data.add(o);
                    }
                    log.error("--------------------"+data.toJSONString()+"-----------------");
                    try {
                        OpenSearchResult result = doc.push(data.toJSONString(),index,tableName);
                        if(!result.getResult().equalsIgnoreCase("true")){
                            QueryEngine.getInstance().executeUpdate(logSql,new Object[]{com.jackrain.nea.core.db.Tools.getSequence("ali_opensearch_log"),
                                    index,tableName,result.getTraceInfo()+"\n"+data.toJSONString(),"N",new Timestamp(System.currentTimeMillis())});
                        }

                    } catch (Exception e) {
                        e.printStackTrace(pw);
                        QueryEngine.getInstance().executeUpdate(logSql,new Object[]{com.jackrain.nea.core.db.Tools.getSequence("ali_opensearch_log"),
                                index,tableName,sw.toString()+"\n"+data.toJSONString(),"N",new Timestamp(System.currentTimeMillis())});

                    }
                    LockSupport.parkNanos(TimeUnit.MILLISECONDS.toNanos(100L));
                }
                return ja.size();
            }else {
                return 0;
            }
        }else {
            return 0;
        }
    }


    /**
     * before db operation
     * @param tableName
     */
    public void initadd(String tableName, Object[] objects,String sql,String index){
        //日志流
        StringWriter sw = new StringWriter();
        PrintWriter pw = new PrintWriter(sw);
        DocumentClient doc = new DocumentClient(client);
        JSONArray ja = QueryEngine.getInstance().doQueryObjectArray(sql,objects);
        if(ja != null){
            int cnt = ja.size()/100;
            int mod = ja.size()%100;
            for(int i=0; i<=cnt; i++){
                JSONArray data = new JSONArray();
                for(int j=0; (j<100&&i<cnt)||(i==cnt&&j<mod); j++){
                    JSONObject o = new JSONObject();
                    o.put(DocumentConstants.DOC_KEY_CMD, Command.ADD.toString());
                    o.put(DocumentConstants.DOC_KEY_FIELDS,ja.get(i * 100 + j));
                    data.add(o);
                }
                try {
                    OpenSearchResult result = doc.push(data.toJSONString(),index,tableName);
                    if(!result.getResult().equalsIgnoreCase("true")){
                        QueryEngine.getInstance().executeUpdate(logSql,new Object[]{com.jackrain.nea.core.db.Tools.getSequence("ali_opensearch_log"),
                                index,tableName,result.getTraceInfo()+"\n"+data.toJSONString(),"N",new Timestamp(System.currentTimeMillis())});
                    }

                } catch (Exception e) {
                    e.printStackTrace(pw);
                    QueryEngine.getInstance().executeUpdate(logSql,new Object[]{com.jackrain.nea.core.db.Tools.getSequence("ali_opensearch_log"),
                            index,tableName,sw.toString()+"\n"+data.toJSONString(),"N",new Timestamp(System.currentTimeMillis())});

                }
                LockSupport.parkNanos(TimeUnit.MILLISECONDS.toNanos(100L));
            }
        }
    }


}
